package com.ruoyi.common.utils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.*;
import java.time.Duration;
import java.time.Instant;
import java.util.Random;

/**
 * 图片曝光不足处理器
 * 功能：
 * 1. 递归遍历目录及其子目录
 * 2. 处理常见图片格式（JPG/PNG/GIF）
 * 3. 应用随机强度曝光不足效果
 * 4. 保持目录结构输出处理结果
 */
public class ImageUnderexposureProcessor {

    public static void main(String[] args) {
        System.out.println("[SYSTEM] 程序启动");
        Path inputDir = Paths.get("C:\\Users\\lenovo\\Desktop\\0-异常数据原图");
        Path outputDir = Paths.get("C:\\Users\\lenovo\\Desktop\\异常数据原图\\过暗");

        Instant startTime = Instant.now();
        processImages(inputDir, outputDir);
        Duration totalDuration = Duration.between(startTime, Instant.now());

        System.out.printf("[SYSTEM] 处理完成! 总耗时: %d分 %d秒%n",
                totalDuration.toMinutesPart(),
                totalDuration.toSecondsPart());
    }

    /**
     * 递归处理图片文件
     */
    public static void processImages(Path inputDir, Path outputDir) {
        try {
            System.out.printf("[PROCESS] 开始扫描目录: %s%n", inputDir.toAbsolutePath());

            Files.walk(inputDir)
                    .filter(Files::isRegularFile)
                    .forEach(filePath -> {
                        try {
                            if (isValidImage(filePath)) {
                                processSingleImage(filePath, inputDir, outputDir);
                            }
                        } catch (Exception e) {
                            System.err.printf("[ERROR] 文件处理失败: %s | 原因: %s%n",
                                    filePath, e.getMessage());
                        }
                    });
        } catch (IOException e) {
            System.err.printf("[FATAL] 目录遍历异常: %s%n", e.getMessage());
        }
    }

    private static void processSingleImage(Path filePath, Path inputDir, Path outputDir)
            throws IOException {
        System.out.printf("[PROCESS] 开始处理: %s%n", filePath);
        Instant start = Instant.now();

        BufferedImage original = ImageIO.read(filePath.toFile());
        System.out.printf("[STATUS] 图片尺寸: %dx%d%n", original.getWidth(), original.getHeight());

        float exposure = generateExposure(0.2f, 0.6f);
        System.out.printf("[PARAM] 曝光系数: %.2f%n", exposure);

        BufferedImage processed = applyUnderexposure(original, exposure);

        // 传递exposure参数到保存方法
        saveProcessedImage(processed, inputDir, outputDir, filePath, exposure);

        Duration duration = Duration.between(start, Instant.now());
        System.out.printf("[SUCCESS] 处理完成 | 耗时: %dms%n%n", duration.toMillis());
    }

    /**
     * 验证图片格式
     */
    private static boolean isValidImage(Path path) {
        String fileName = path.getFileName().toString().toLowerCase();
        return fileName.matches(".*\\.(jpg|jpeg|png|gif)$");
    }

    /**
     * 生成随机曝光系数（保留两位小数）
     */
    private static float generateExposure(float min, float max) {
        return Math.round((min + new Random().nextFloat() * (max - min)) * 100) / 100.0f;
    }

    /**
     * 应用曝光不足算法
     */
    private static BufferedImage applyUnderexposure(BufferedImage image, float exposure) {
        BufferedImage result = new BufferedImage(
                image.getWidth(),
                image.getHeight(),
                BufferedImage.TYPE_INT_RGB);

        // 遍历每个像素
        for (int y = 0; y < image.getHeight(); y++) {
            for (int x = 0; x < image.getWidth(); x++) {
                int pixel = image.getRGB(x, y);

                // 分解RGB通道
                int r = Math.max(0, (int)(((pixel >> 16) & 0xFF) * exposure));
                int g = Math.max(0, (int)(((pixel >> 8) & 0xFF) * exposure));
                int b = Math.max(0, (int)((pixel & 0xFF) * exposure));

                // 重组像素并限制最小值
                int newPixel = (r << 16) | (g << 8) | b;
                result.setRGB(x, y, newPixel);
            }
        }
        return result;
    }

    /**
     * 保存处理后的图片（新增文件名处理逻辑）
     */
    private static void saveProcessedImage(BufferedImage image, Path inputDir,
                                           Path outputDir, Path srcPath, float exposure) throws IOException {
        // 原始文件名处理
        String originalName = srcPath.getFileName().toString();
        int dotIndex = originalName.lastIndexOf('.');

        // 分割文件名和扩展名
        String baseName = (dotIndex == -1) ? originalName : originalName.substring(0, dotIndex);
        String extension = (dotIndex == -1) ? "" : originalName.substring(dotIndex);

        // 构建新文件名（格式：原名称_系数.扩展名）
        String newFileName = String.format("%s_%.2f%s", baseName, exposure, extension);

        // 构建新的相对路径
        Path relativePath = inputDir.relativize(srcPath).getParent();
        Path outputPath = outputDir.resolve(relativePath == null ? null : relativePath);
        outputPath = outputPath.resolve(newFileName);

        // 创建目录并保存
        Files.createDirectories(outputPath.getParent());
        String format = getFileFormat(originalName);
        ImageIO.write(image, format, outputPath.toFile());
        System.out.printf("[OUTPUT] 已保存至: %s%n", outputPath);
    }

    /**
     * 获取文件格式
     */
    private static String getFileFormat(String fileName) {
        if (fileName.toLowerCase().endsWith(".png")) return "PNG";
        if (fileName.toLowerCase().endsWith(".gif")) return "GIF";
        return "JPEG"; // 默认JPEG格式
    }
}